home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i055: uucp 1.03D - unix compatible uucp/mail/news system, Part11/16
- Message-ID: <11294@xanth.cs.odu.edu>
- Date: 4 Feb 90 02:39:33 GMT
- Sender: tadguy@cs.odu.edu
- Reply-To: overload!dillon (Matt Dillon)
- Lines: 2227
- Approved: tadguy@cs.odu.edu (Tad Guy)
- X-Mail-Submissions-To: Amiga@cs.odu.edu
-
- Submitted-by: overload!dillon (Matt Dillon)
- Posting-number: Volume 90, Issue 055
- Archive-name: unix/uucp-1.03d/part11
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 11 (of 16)."
- # Contents: man/dmail.help src/uucico/uucico.c
- # Wrapped by tadguy@xanth on Sat Feb 3 20:51:18 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'man/dmail.help' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'man/dmail.help'\"
- else
- echo shar: Extracting \"'man/dmail.help'\" \(23648 characters\)
- sed "s/^X//" >'man/dmail.help' <<'END_OF_FILE'
- X
- X'help TOPIC' for more information on a command. Many commands take
- Xmessage numbers or message lists:
- X [msg] is an optionaly specified message number (usually the
- X operation is on the current message if no number is
- X specified)
- X <list> is an optionaly specified message list. Message lists
- X consists of number ranges of the form N -N N- or N-N, and
- X keywords (help keywords)
- X
- X
- XOTHER HELP AVAILABLE (in addition to the commands):
- X pager sendmail tilde header newmail keywords enviroment
- X
- XDMAIL written by Matthew Dillon, U.C. Berkeley -UCF
- X
- X(C)Copyright 1985-1989 by Matthew Dillon, All Rights Reserved
- X
- X.pager
- Xset page [rows/command]
- X
- X 'page' is a SET variable which determines the type of paging list and
- Xdisplay commands will use. If not defined, no filter is used. If a numerical
- Xvalue (i.e. 24) is specified, the page length will be set to that value and
- Xa rather stupid, simple internal paging routine will be used. If the
- Xvariable is set to an alpha-numeric string, output will be piped through
- Xthat filter. For instance:
- X
- X unset page -no paging
- X set page more -use more filter
- X set page page -use 'page' filter
- X set page > x -redirect to a file (be careful)
- X set page 24 -use internal paging, page length 24 rows.
- X
- X For internal paging, use <return> to continue, or your INTR
- Xcharacter to break out. Note that if you have paging set to a program,
- Xresponse time may be slower because dmail must execute that program.
- X
- X.sendmail
- Xset sendmail sendmail-path
- X
- X Inform DMAIL as to where the sendmail program is. The default
- X(variable unset) is /usr/lib/sendmail. This variable is useful only for
- Xthose of us who like to hack-up our own sendmail.
- X
- X.tilde
- X~ ~user directory expansion
- X
- X In all expressions except those within double quotes, the tilde
- X`~` will be expanded to either your home directory, or the directory of
- Xa specified user, depending. Note that '*' and '?' are not expanded by
- XDMAIL, though they will be by any shell commands you execute.
- X
- X It is probably a good idea to use ~ in any aliases, etc... in case
- Xyou change directories using the 'cd' command.
- X
- X alias resource source ~/.dmailrc -example using ~
- X
- X.header
- Xset header filepath
- X
- X Set the location of your header file, which will appended to the
- Xscratch mail file before you are placed in the editor (usually vi).
- X
- X set header ~/.header -set header file to ~/.header
- X unset header -no header file
- X
- X.newmail
- XWhen new mail comes in:
- X
- X Whenever newmail arrives, it will be automatically incorporated into
- Xa running DMAIL. However, to see it, you must 'select all' (or select on
- Xanything that would include it).
- X
- X.keywords
- X.range
- X.message
- XKEYWORDS, MESSAGE LISTS
- X
- X Many commands in DMAIL require a range of messages be given. A Range
- Xconsists of message numbers (3 4 5), message ranges (1-45 -9 9-), and
- Xkeywords. Keywords select certain messages from the entire SELECTED list:
- X
- X all -All messages
- X tag -All TAGGED messages
- X mark -All MARKED (read) messages
- X deleted -All DELETED messages
- X written -All WRITTEN messages
- X untag -All messages NOT TAGGED
- X unmark -All messages NOT MARKED (i.e. read)
- X undeleted -All messages NOT DELETED
- X unwritten -All messages NOT WRITTEN
- X
- X Only the first three letters need be specified. For instance, the
- X'all' keyword selects all the messages currently selected. You could select
- Xon some subject, say, and then 'delete all'.
- X
- X The message number 0 refers to the last message. the 'undeleted'
- Xkeyword exists only for completeness; you will probably never use it.
- X
- X.ver
- X.version
- XVER
- X
- X returns the version number.
- X
- X.if
- X.else
- X.endif
- XIF [!]variable
- XELSE
- XENDIF
- X
- X Conditionals. Example:
- X
- X if verbose
- X .... do stuff if the variable exists
- X else
- X ... do stuff if the variable does not exist
- X endif
- X if !page; echo no page variable; endif
- X
- X.nobreak
- X.breakok
- XNOBREAK
- XBREAKOK
- X
- X Disable or Enable your INTR key. This command is stackable, thus
- Xthere is no problem with recursive aliases which use it. Be careful that
- Xyou match any NOBREAK to a BREAKOK, or you may accidently put yourself into
- XNOBREAK mode (and a single BREAKOK may not fix it because it's stackable).
- X
- X A good example would be a command which needs the page variable set
- Xfor the duration... say an alias to TYPE to a file:
- X
- Xalias file "%_a nobreak; set _b $page; set page cat > $_a; type; set page $_b; unset _b; breakok"
- X
- X You can see that if the user were to hit his INTR character at the
- Xwrong time, the page variable would be incorrectly set. The nobreak/breakok
- Xcommands fix this problem. For simplicity, most people don't bother with
- Xbreak/nobreak, as it clutter's aliases up.
- X
- X.delete
- XDELETE <message list>
- X
- X Mark the specified messages for deletion. They will no longer show up
- Xon LISTings, (gaps will appear in message numbering). However, you can
- Xstill TYPE them, if you remember the message number, and you can always
- XUNDELETE them. Remember that the particular message # you've deleted
- Xmay be different if you change the SELECT parameters. For example,
- Xmessage #3 selecting 'To' & 'foo' may actually be message #45 when you
- Xare selecting ALL (see SELECT). Upon a QUIT, messages marked for
- Xdeletion are actually deleted from the mail file.
- X
- X.undelete
- XUNDELETE <message list>
- X
- X UNDELETES messages. Without arguments, UNDELETE will
- Xrestore the last message you deleted. Specifying 'all' (undelete all), will
- Xundelete any deleted messages in the currently selected message list.
- X
- X.header
- XHEADER [message]
- X
- X Display the entire header of a message. This does not cause the
- Xmessage to be marked 'read'. TYPE, on the other hand, only displays
- Xheader information specified by SETLIST.
- X
- X.type
- XTYPE [message]
- X
- X Type the text of a message. Only header fields defined by SETLIST
- Xare displayed. Otherwise, only the text is displayed. This marks
- Xthe particular message as 'read', and also makes that message the
- Xcurrent message.
- X
- X.echo
- XECHO [string]
- X
- X Echo the given string onto the screen.
- X
- X.go
- XGO #
- X go to a message, don't type it out or anything. Remember that you
- Xcan go to the last message by using the message # 0. By placing a keyword
- X(help range), you can go to the first TAGGED message, etc...
- X
- X.reply
- X.Reply
- XREPLY
- X
- X Reply to the current letter. There are two forms of 'reply'. The
- Xfirst does not include the senders original letter, the second does.
- XIn both cases, Dmail will place you in VI, with the To:, Cc:, and
- Xsubject lines filled out. The second form is 'Reply', with an
- Xupper case 'R'. This form includes the sender's message shifted to
- Xthe right with '>'s on the left hand side. See FORWARD for another
- Xmethod of replying to mail.
- X
- X In any case, you may get the sender's letter by reading the file '#'
- Xfrom VI. That sequence would be ':r\\#'
- X
- X See MAIL for more information on VI
- X
- X.forward
- XFORWARD [user user user....]
- X
- X Forward the current message to a list of users. The sender's
- Xentire message is placed in the text portion. The To: field will
- Xcontain the user's named above, and the Subject: field will contain
- Xa 'Fo:' (you append your own subject)
- X
- X See MAIL for more information on VI
- X
- X.mail
- XMAIL [user user user user...]
- X
- X Mail to [users]. You are given a VI to work from, and may modify
- Xany of the header fields. the From: field is inserted automatically
- Xby SENDMAIL, but you can overide it if you wish.
- X
- X Quitting out of VI without writing the output file will cause an
- Xabort, and no mail will be sent. Additionaly, you may use the 'vibreak'
- Xvariable to enable your INTR character (usually CTL-C) to break you out of
- XVI.
- X
- X When modifying the users list in To and Cc fields, remember that
- Xthey should be all comma delimited, or none comma delimited.
- X
- X.select
- XSELECT ALL
- XSELECT Field match match match match...
- XSELECT Field !match
- XSELECT Field match match match , Field match , .....
- X
- X Select what you want to look at. Select will take the field header
- Xyou supply and attempt to match arguments with that field in the mail
- Xfile. You can then work on the selected material as if the rest of
- Xyour mail didn't exist. For instance, 'select To dillon', will select
- Xall messages addressed to you. Note that case is checked for the
- XFIELD-HEADER, but not for arguments, so the latter will also find
- Xanything addressed to Dillon or DILLON. You only have to give a
- Xpartial match, so 'select To di' would work just as well.
- X
- X Select then, allows you to quickly find what you want even though
- Xyou may have 12000 messages (though it may take a while with that many)
- XYou may also specify what you DON'T want to select on:
- X
- X select To !foo
- X
- Xwill select all letters not addressed to 'foo'. You may select on any
- Xfield you wish. At any time, you may say 'select ALL' to select the
- Xentire message list. Use RESELECT to select on the current message
- Xlist. SELECT always selects from the entire message-list
- X
- X select Cc hack , To hack
- X
- Xwill select any mail with Cc or To fields containing hack. You may
- Xhave as many comma operators as you wish. The comma must be a field
- Xof its own (spaces on either side... will be fixed in a later version)
- X
- X.reselect
- XRESELECT ALL
- XRESELECT Field match match match match...
- XRESELECT Field !match
- X
- X SEE SELECT. Reselect allows you to CONTINUE to narrow down a topic
- Xor whatever. It will select on the current message list (which you have
- Xalready narrowed down with SELECT or RESELECT).
- X
- X.defer
- XDEFER
- X
- X Deselects any marked messages .. messages marked as 'read'. This is
- Xas if you did a RESELECT on all unread messages in the current select field.
- XThus, the messages will be renumbered. To see these messages again, you must
- Xuse SELECT.
- X
- X.rlist <num>
- XRLIST <num> -<num> > 0 (next N), < 0 (prev N).
- XRLIST -Lists next 20 (or previous 20 if near the end)
- X
- X Relative list. See LIST for details of the list command. This
- Xcommand will display the next <num> messages beginning at the current
- Xmessage. If <num> is negative, it displays the previous 20 ending at
- Xthe current message. If there are not enough messages remaining in the
- Xforward or reverse direction, it lists in the opposite direction to try
- Xto bring the total messages listed to <num>
- X
- X.list
- XLIST <message list>
- XLIST -Lists all selected messages
- X
- X Display header information on a message as specified by SETLIST,
- Xin a one line per message format. The default lists ALL messages.
- X
- XLeftword flags: r -indicates message has been read. Message will be
- X moved to the destination file on QUIT
- X > -indicates message is the current message
- X w -indicates message has been written to a file.
- X Message will be deleted from source file on QUIT
- X T -indicates message has been taged by the user
- X
- X.next
- XNEXT
- X
- X Execute TYPE or HEADER for the next message, depending on which of
- XTYPE or HEADER was last executed by you
- X
- X._next
- X_NEXT
- X
- X Go to next message, do not print it out.
- X
- X.back
- XBACK
- X
- X Execute TYPE or HEADER for the previous message, depending on which
- Xof TYPE or HEADER was last executed by you
- X
- X._back
- X_BACK
- X
- X Go to previous message, do not print it out.
- X
- X.db
- XDB
- X Delete the current message, type (or header) the previous message.
- XThis command could not be implemented with "del;prev" due to a special case
- Xwhen one is on the last message.
- X
- X.dt
- XDT
- X Delete current message, type (or header) next message. This command
- Xwill warn you when you reach the end of the message list.
- X
- X References: DELETE and NEXT
- X
- X.enviroment
- XENVIROMENT VARIABLE ACCESS
- X
- X Access may be gained to enviroment variables by using $$ instead of
- X a single $. For example: echo $$USER
- X
- X 'help dmail' for command line options,
- X 'help set' for description of special variables
- X
- X.set
- XSET [variable [string]]
- X
- X see 'enviroment' for enviroment variables
- X
- X With no arguments, SET prints out all currently active variables.
- XNote that this variable list is a different list than the ALIAS list. With
- Xone argument, the specified variable is displayed if it exists, or created
- Xif it doesn't. With more than one argument, the specified variable is set
- Xto the specified string. Variables may be references on the command line by
- X$variable . The variable's contents will replace the reference. Unlike
- Xaliases, however, variable substitutions may take place anywhere on the
- Xcommand line rather than substitute just the command name. Note also that
- Xif you use a $ substitution for an argument of a command, the entire
- Xvariable's contents is ONE argument (i.e. if a = "b c d", and you say
- Xsomething like: 'unset $a', it would attempt to unset a single variable
- Xwhos name is "b c d".
- X
- X There are several reserved SET variables, which define options in
- XDMAIL. Changing these will modify the option:
- X
- X page set paging on or to a specific command (i.e. more)
- X sendmail set the path to the sendmail program
- X vibreak enable your INTR character even when in VI.
- X verbose reflects verbose option to sendmail
- X comlinemail set when dmail executed w/ command line mailing list
- X header header file to append to any messages you send.
- X ask ask what to do after vi'ing mail
- X archive file to archive any mail you send out in.
- X _headchar string used to precede included text, default ">"
- X replyfields fields to search to find the reply path
- X
- X page
- X
- X This variable determines what kind of paging is used for LIST,
- X TYPE, and HEADER commands. If the variable does not exist, paging
- X is turned off. If set to null (no string), an internal paging
- X routine is used. If set to a value, an internal paging routine is
- X used using the value as the page length. the 'page' variable can
- X also be set to a command, such as 'more' or 'page', in which case,
- X the output is piped through those commands:
- X
- X set page Turn paging on (internal page routine)
- X set page 25 Internal page routine... 25 rows/screen
- X set page more Use 'more' command to pipe output through
- X set page page Use 'page' command to pipe output through
- X
- X you could also conceviably say: 'set page cat > x', or
- X 'set page cat | lpr', but be very careful.
- X
- X sendmail
- X
- X This variable will redirect DMAIL as to where the mailer program
- X is. The mailer program must be compatible with /usr/lib/sendmail
- X which is the default used if the 'sendmail' variable isn't set
- X to anything:
- X
- X set sendmail bin/mysendmail
- X
- X vibreak
- X
- X This variable, when set, allows the INTR character to abort a
- X reply, mail, or forward command. Otherwise, if this variable is
- X not present, INTR will not abort the above commands.
- X
- X verbose
- X
- X This variable, when set, causes the -v flag to be sent to
- X sendmail. In addition, DMAIL will wait for sendmail to complete
- X before returning your prompt.
- X
- X comlinemail
- X
- X This variable is set when dmail is invoked with a command line
- X user list (e.g. dmail charlie mary mark). Usually, one uses
- X this variable in an IF construct. A good example would be that
- X you may usually CD to a mail directory, but you don't want to
- X CD when dmail is run with a command line user-list:
- X
- X if !comlinemail
- X cd ...
- X
- X alternate definition: The comlinemail variable will NOT be set
- X if dmail is in interactive mode.
- X
- X header
- X
- X The file specified by this variable will be appended onto the temp
- X vi files in reply and mail. The file is appended before you go into
- X vi, so when you do, what you see is still what you get.
- X
- X ask
- X
- X If set, dmail will ask you what to to (quit, send, re-edit) after you
- X leave the editor when sending mail. If not set, the mail is sent as
- X soon as you leave the editor (unless you didn't write anything).
- X
- X archive
- X
- X If set (to a file name), any mail you send out (mail/reply/etc...)
- X will be archived to this file. Usually, you provide a fully
- X specified path so cd's won't effect the file location.
- X
- X _headchar
- X
- X This string is prepend to any included text when you do an upper-case
- X reply (R) command.
- X
- X replyfields
- X
- X This string holds a list of fields which are searched for to
- X determine which one to use in the To: field of your reply. If
- X this variable does not exist or none of the specified fields could
- X be found, the 'From ' (not From:) mail header will be used. The
- X search ends at the first field found. Example:
- X
- X set replyfields "Reply-To: From:"
- X
- X.replyfields
- XSET replyfields "field1 field2 ..."
- X
- X This string holds a list of fields which are searched for to
- X determine which one to use in the To: field of your reply. If
- X this variable does not exist or none of the specified fields could
- X be found, the 'From ' (not From:) mail header will be used. The
- X search ends at the first field found. Example:
- X
- X set replyfields "Reply-To: From:"
- X
- X.>
- XSET _HEADCHAR "string"
- X
- X see SET. The _headchar variable determines the string prepending all
- X included text when you do an upper-case reply (R) command.
- X
- X.archive
- XSET ARCHIVE file
- X
- X if the archive variable is set to a file path, any mail you send out
- X will automatically be appended to that file. Dmail pre-pends a
- X "From ", so it is compatible with /bin/mail and so that you can
- X dmail -f your archive file. Additionaly, a "Date: " field is
- X pre-pended so you know when you sent the message. example:
- X
- X set archive ~/Dmail/arch
- X
- X since your .dmailrc is sourced even when you "dmail user .." from
- X your csh, putting the above line in your .dmailrc will turn on
- X archiving whenever you use dmail to send mail, command line or
- X dmail prompt.
- X
- X if unset or set to nothing, no archive is made.
- X
- X.ask
- XSET ASK
- X
- X if the 'ask' variable is set (set ask), dmail will ask you what to do
- X when you are finished editing mail rather than send it immediately.
- X (see 'help set')
- X
- X.alias
- XALIAS [variable [string]]
- X
- X Create an alias for a command. With no arguments, ALIAS will display
- Xall active aliases. With one argument, a particular alias is displayed (if
- Xit exists), or defined (if it did not previously exist). With more than one
- Xargument, the particular alias is set to the string list specified.
- X
- Xalias
- Xalias hack "select From hacker , To hacker , Cc hacker"
- Xalias bye quit
- Xalias stuff "setlist 60 To ; list"
- X
- X Usually, any arguments following the alias are appended to the
- Xexpansion. However, you can place such arguments inside the alias somewhere
- Xby using the following construction:
- X
- Xalias myecho "%var echo $var ; list"
- X
- Xmyecho hello there ---> echo hello there ; list
- X
- X to unalias an alias, use the UNALIAS command.
- X
- X.unset
- X.unalias
- XUNSET var var var...
- XUNALIAS var var var...
- X
- X Eradicate variables or aliases from memory.
- X
- X.setlist
- XSETLIST [-s] [columns] Field [columns] Field ...
- X
- X -s prevents display of the list.
- XSet the list format used for LIST and TYPE. The optional [columns]
- Xindicates how many columns to allocate for the Field specified. The
- XField can be a partial match. However, case is observed:
- X
- Xsetlist 18 Fro 38 Sub 10 To 0 Dat
- X
- X18 columns for the From: field, etc... when TYPEing messages, the
- X[columns] is ignored, and each field is printed in its entirety.
- XNote that 0 columns have been allocated for the Date: field.
- XTherefore, the Date: field will not show up on the LIST command,
- Xbut will show up in the TYPE command.
- X
- X.cd
- XCD PATH
- X
- X cd, as in csh. Changes your base directory. You can use
- X the shell escape '! pwd' to get your current working directory.
- X
- X.source
- XSOURCE file
- X
- X Source a file. The file is read in an executed in sequence.
- X
- X.preserve
- XPRE <message list>
- X
- X PRESERVE messages. A message is MARKED if it has been read (has an 'r'
- Xflag from the LIST command). Marked messages are moved from your readfile
- Xinto your outfile upon a QUIT. If you are reading and writing to the same
- Xfile (i.e. from your mbox to your mbox), the 'r' flag has no effect.
- X
- X However, if you are reading from your spool file, and want to keep
- Xread messages in your spool (that is, not move them to your mbox), you want
- Xto PRESERVE them. This command simply unmarks them, so they appear not to
- Xhave been read.
- X
- X.mark
- XMARK <message list>
- X
- X Mark messages specified as being already 'read'. Remember that if
- Xyou executed DMAIL without a -f option, any message 'read' at the time
- Xyou quit will be moved to MBOX (or file specified by -o)
- X
- X.tag
- X.untag
- XTAG <list>
- XUNTAG <list>
- X
- X The TAG command allow you to flag any message. You can tag a set of
- Xmessages, then reference them all at once. For instance, if you tag
- Xinteresting messages as you glance at them, you may then write them all
- Xto a file by 'write filename tag', or list them with 'list tag'.
- XAlternately, you could delete all your taged messages with a single delete
- Xcommand 'delete tag'. The 'tag' operand works in the same way as the 'all'
- Xoperand, except it works only on taged messages.
- X
- X UNTAG will untag a particular message in your message list. For
- Xinstance, to untag any taged messages in the entire message list, you would:
- X
- X select all
- X untag all OR untag tag
- X
- X Note that 'untag all' and 'untag tag' have the same effect.
- X
- X.write
- XWRITE file <message list>
- X
- X Write the given messages or the current message to a file. The file
- Xfile is appended to. Remember that you may specify 'all' to write
- Xall messages in the current select field to the file. Messages will be
- Xmarked as having been writen, and will be deleted from the mail file
- Xwhen you 'quit'. However, you may cause them to be kept in the mail
- Xfile by UNdeleting the messages (i.e. undelete all)
- X
- X You can also TAG the messages you want to write, and say
- X'write file tag' to write to the file all taged messages.
- X
- X.!
- X! [shell command]
- X
- X Give yourself a shell or execute a shell command. The shell forked
- Xis that specified by your SHELL enviroment variable, or /bin/sh if there is
- Xno SHELL enviroment variable.
- X
- X.x
- X.exit
- XX (EXIT)
- X
- X EXIT out of DMAIL without changing any files. Usually, one exits
- Xwith QUIT, which would cause deleted messages to disappear, and TYPEd
- Xmessages to go to MBOX (if you did not use the -f option with DMAIL).
- X
- X If your outfile is the same as your infile, reading a message does
- Xnot effect anything.
- X
- X.quit
- XQUIT
- X
- X Quit out of DMAIL. Delete any messages that were marked for deletion
- Xand if you executed DMAIL on /usr/spool/mail/ (default), any mail
- Xmarked 'read' will be placed in MBOX in your home directory
- X
- X.xswitch
- X.qswitch
- XXSWITCH fromfile [tofile]
- XQSWITCH fromfile [tofile]
- X
- X Switch to a different set of files. XSWITCH doesn't modify your
- Xold from and to files before switching, QSWITCH works as if you had QUIT
- Xstuff before switching to another set of files.
- X
- X If no [tofile] is specified, the new tofile will be the same as the
- Xfromfile you specify.
- X
- X.help
- X.?
- XHELP [topic]
- X
- X Give me help on a topic
- X
- X.dmail
- XCOMMAND LINE OPTIONS FOR DMAIL
- X
- X dmail -O [-l rcfile] -f [file] -o [file] -F field -F field -F field ...
- X
- X Default conditions:
- X Home directory gotten from password entry
- X User gotten from password entry
- X Visual editor set to /usr/ucb/vi
- X
- X VI BREAKOUT enabled
- X READ file is /usr/spool/mail/$USER
- X WRITE file is $HOME/mbox
- X From:, To:, and Subject: fields will be loaded into memory.
- X
- X HOME enviroment variable becomes home directory
- X USER enviroment variable becomes user name
- X VISUAL enviroment variable becomes editor used
- X
- X -O Go into interactive mode, even if there is no
- X mail to read.
- X
- X -f [from file] Specify spool file to get mail from. If no file
- X Argument is given, $HOME/MBOX is used.
- X
- X -o [to file] Specify file to write to, If no Argument
- X is given, $HOME/.MBOX is used. Note that
- X the default without -o is $HOME/MBOX
- X
- X -f -o With no file arguments causes both READ and
- X WRITE files to be $HOME/.MBOX
- X
- X -F field Append this field to those which will be
- X used on initial load. If, During usage of the
- X program you specify a field which is not in
- X memory, DMAIL will be forced to re-load the
- X entire spool file, which can take a long time
- X if you have more than 64K in the file
- X
- X -l rcfile Use this as the rc file rather than .dmailrc
- X
- X -L Do not source the rc file on boot
- X
- X
- END_OF_FILE
- if test 23648 -ne `wc -c <'man/dmail.help'`; then
- echo shar: \"'man/dmail.help'\" unpacked with wrong size!
- fi
- # end of 'man/dmail.help'
- fi
- if test -f 'src/uucico/uucico.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/uucico/uucico.c'\"
- else
- echo shar: Extracting \"'src/uucico/uucico.c'\" \(32949 characters\)
- sed "s/^X//" >'src/uucico/uucico.c' <<'END_OF_FILE'
- X
- X/*
- X * UUCICO.C
- X *
- X * (C) Copyright 1987 by John Gilmore.
- X * Copying and use of this program are controlled by the terms of the Free
- X * Software Foundation's GNU Emacs General Public License.
- X *
- X * Derived from:
- X * i[$]uuslave.c 1.7 08/12/85 14:04:20
- X * which came from the ACGNJ BBS system at +1 201 753 9758. Original
- X * author unknown.
- X *
- X * Ported to Amiga by William Loftus
- X * Amiga Changes Copyright 1988 by William Loftus. All rights reserved.
- X * Additional Major Changes (c)Copyright 1989 by Matthew Dillon, All rights reserved
- X *
- X * 14-Oct-89, moved modem_init() to before poll_sys.
- X *
- X * -r option (-r1 does a call out to all systems we have mail for)
- X * -D[EVICE] dev sets serial device name (automatic from Getty)
- X * -U[NIT] unit sets unit name (automatic from Getty)
- X * -h0 Ignore CD (carrier detect)
- X */
- X
- X#include "/version.h"
- X
- X#include "includes.h" /* System include files, system dependent */
- X#include "uucp.h" /* Uucp definitions and parameters */
- X#include "sysdep.h" /* System dependent parts of gnuucp */
- X#include "modem.h" /* Modem commands */
- X#include <log.h>
- X#include <tmpfile.h>
- X
- Xint sigint();
- Xvoid modem_init();
- Xvoid cleanup();
- X
- X#define MAX_FLAGS 40
- X
- Xextern int errno;
- X
- XIDENT(".06");
- X
- Xstatic char *Copyright = COPYRIGHT;
- X
- Xchar ttynam[NAMESIZE], /* Name of tty we use as serial port */
- X srcnam[NAMESIZE], /* Source file name */
- X dstnam[NAMESIZE], /* Dest file name */
- X who[NAMESIZE] = "-", /* Who sent the file */
- X flags[MAX_FLAGS], /* Flags from file xfer cmd */
- X temp[NAMESIZE]; /* Temp file name */
- X
- Xint ourpid = 0, /* Our process ID */
- X ignore_time_restrictions = 0, /* Call out even if L.sys sez no */
- X mode; /* File mode from file xfer cmd */
- X
- Xchar host_name[MAX_HOST] = "AmigaUUCP"; /* Other guy's host name */
- Xchar our_name[MAX_HOST]; /* Our uucp hostname, set from usenet.ctl */
- Xchar path[128];
- Xint debug = -1; /* -1 indicates not set by command line or ctl file */
- Xint f_wait = 0; /* wait for a call (-w) or calls (-w -e) after outbnd */
- Xint loop = 0; /* Loop accepting logins if tty name specified */
- Xint curtemp = 0;
- Xint Overide = 0; /* overide modem protocol */
- Xint Getty = 0; /* -Getty initiated */
- Xint IgnoreCD= 0; /* xgetc() should ignore carrier? */
- Xint OurNameOv= 0;
- Xint WindowOne= 0;
- X
- X#define MAX_STRING 200 /* Max length string to send/expect */
- X
- X#define MSGO2IDX 7
- X
- X/* We print these prompts */
- X
- Xchar msgo0[] = "login: ";
- Xchar msgo1[] = "Password:";
- Xchar msgo2[10+MAX_HOST] = { "\20Shere" }; /* NO = */
- Xchar msgo3[] = "\20ROK\0";
- Xchar msgo3a[]= "\20P";
- Xchar msgo3b[]= "\20Pg\0";
- Xchar msgo4[] = "\20OOOOOOO\0";
- X
- X/* We expect to receive these strings */
- X
- Xchar msgi0[] = "uucp\r";
- Xchar msgi1[] = "s8000\r";
- X/* char msgi2[] = "\20S*\0"; We now scan it specially FIXME */
- Xchar msgi3[] = "\20Ug\0";
- Xchar msgi4[] = "OOOOOO";
- X
- X#define SPOOLDIR "UUSPOOL:"
- X
- X/*
- X * Protocol switch data structure
- X */
- X
- Xextern int gturnon(), grdmsg(), gwrmsg(), grddata(), gwrdata(), gturnoff();
- X
- X#define turnon gturnon
- X#define rdmsg grdmsg
- X#define wrmsg gwrmsg
- X#define rddata grddata
- X#define wrdata gwrdata
- X#define turnoff gturnoff
- X
- Xint
- Xgetname(isshere)
- X{
- X int data, count = 0;
- X static char msgi[MAX_STRING+SLOP]; /* Incoming trash buffer */
- X
- X /* Read data until null character */
- X
- X while ((data = xgetc(BYTE_TO)) != EOF) {
- X data &= 0x7F;
- X if (data == 020)
- X break;
- X }
- X if (data == EOF)
- X return FAIL;
- X
- X while ((data = xgetc(BYTE_TO)) != EOF && (data & 0x7F)) {
- X data &= 0x7F;
- X if (count == 0 && data != 'S')
- X continue;
- X if (count > sizeof(msgi) - 2)
- X continue;
- X msgi[count++] = (char)data;
- X }
- X msgi[count] = 0;
- X
- X if (debug > 8)
- X printf("GETNAME MSG (%d): %s\n", count, msgi);
- X
- X if (msgi[0] != 'S')
- X return FAIL;
- X if (isshere) {
- X for (count = 1; msgi[count] && msgi[count] != '='; ++count);
- X if (msgi[count] == '=')
- X ++count;
- X } else {
- X count = 1;
- X }
- X if (msgi[count]) {
- X if (debug > 8)
- X printf("Compare host names: '%s' '%s'\n", host_name, msgi + count);
- X strcpy (host_name, msgi + count);
- X }
- X strtok(host_name, " "); /* put \0 after hostname */
- X if (debug > 8)
- X printf("Hostname is '%s'\n", host_name);
- X return SUCCESS;
- X}
- X
- X/*
- X * get_proto() checks the list of protos given by the foriegn machine
- X * checking for 'g' (which is the only proto we have). Use only in master
- X * mode.
- X */
- X
- Xint
- Xget_proto()
- X{
- X int data;
- X
- X while ((data = xgetc(BYTE_TO)) != EOF) {
- X data &= 0x7F;
- X if (data == 0)
- X break;
- X if (data == 'g')
- X return(SUCCESS);
- X }
- X return FAIL;
- X}
- X
- X/*
- X * Medium level input routine.
- X *
- X * Look for an input string for the send-expect sequence.
- X * Return 0 for matching string, 1 for timeout before we found it.
- X * FIXME: we only time out if the other end stops sending. If it
- X * keeps sending, we keep listening forever.
- X */
- X
- Xinstr(s, n)
- Xchar *s;
- Xint n;
- X{
- X int data,count,j;
- X int i;
- X static char msgi[512]; /* Incoming trash buffer */
- X
- X count = 0;
- X
- X if (debug > 8) {
- X printf("Expecting ");
- X for (i = 0; i < n; i++)
- X printc(s[i]);
- X printf("\n");
- X }
- X
- X while ((data = xgetc(BYTE_TO)) != EOF) {
- X msgi[count++] = (char)data & 0x7F;
- X
- X if (count == sizeof(msgi)) { /* throw away first half */
- X count = sizeof(msgi) / 2;
- X bcopy(msgi + sizeof(msgi) / 2, msgi, sizeof(msgi) / 2);
- X }
- X
- X if (count >= n) {
- X for (i = n - 1, j = count - 1; i >= 0; i--, j--) {
- X if (*(s+i) != msgi[j])
- X break;
- X }
- X if (i < 0) {
- X if (debug > 8)
- X printf("\n");
- X return(0);
- X }
- X }
- X }
- X
- X if (debug > 8)
- X printf("\n");
- X msgi[count] = (char)0;
- X return(1);
- X}
- X
- X/*
- X * Debugging hack for stuff written to the modem.
- X */
- X
- Xint
- Xtwrite(s, n)
- Xchar *s;
- Xint n;
- X{
- X int i;
- X
- X if (debug > 8) {
- X printf("Wrote: ");
- X for (i = 0; i < n; i++)
- X printc(s[i]);
- X printf("\n");
- X }
- X return xwrite(s, n);
- X}
- X
- X
- X/*
- X * MAIN ROUTINE.
- X *
- X * This is called at program startup. It parses the arguments to the
- X * program (if any) and sets up to receive a call on the modem.
- X *
- X * If there are no arguments, we assume the caller is already on standard
- X * input, waiting to do uucp protocols (past the login prompt), and we
- X * just handle one caller.
- X *
- X * If there is an argument, it is the name of the tty device where we
- X * should listen for multiple callers and handle login and password.
- X */
- X
- Xvoid
- Xmain(argc,argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i;
- X char *poll_sys = (char *)NULL; /* System name to poll, or none */
- X short rmode = 0; /* 1 = master, 0 = slave */
- X
- X LogProgram = "uucico";
- X LogHost = host_name;
- X LogWho = who;
- X
- X signal(SIGINT,sigint); /* Allow the user to break */
- X
- X /* FIXME, use getopt */
- X /* scan command line arguments, kinda kludgy but it works */
- X
- X for (i = 1; i < argc; ++i) {
- X if (argv[i][0] != '-') {
- X printf("uucico: warning, extra args ignored: %s\n", argv[i]);
- X break;
- X }
- X switch (argv[i][1]) {
- X case 'N':
- X strcpy(our_name, argv[i] + 2);
- X OurNameOv = 1;
- X break;
- X case 'D': /* Serial Device */
- X {
- X extern char *DeviceName;
- X DeviceName = argv[++i];
- X }
- X break;
- X case 'U': /* Serial Unit */
- X {
- X extern long DeviceUnit;
- X DeviceUnit = atoi(argv[++i]);
- X }
- X break;
- X case 'g':
- X case 'G':
- X Getty = 1;
- X break;
- X case 'h':
- X IgnoreCD = atoi(argv[i] + 2);
- X break;
- X case 'w':
- X ++f_wait;
- X break;
- X case 'r':
- X rmode = atoi(&argv[i][2]);
- X break;
- X case 'x':
- X debug = atoi(&argv[i][2]);
- X LogLevel = debug;
- X LogToStdout = 1;
- X printf("uucico: debug level set to %d\n", debug);
- X break;
- X case 'o':
- X Overide = 1;
- X break;
- X case 'n':
- X WindowOne = 1; /* force windowing mode to size=1 */
- X break;
- X case 'S':
- X ignore_time_restrictions++;
- X case 's':
- X poll_sys = &argv[i][2];
- X break;
- X case 'e':
- X ++loop;
- X break;
- X /* Is -t needed for MSDOS? Why? -- hoptoad!gnu */
- X case 't':
- X curtemp++;
- X printf("uucico: using ~uutemp.$$$ for temp file\n");
- X break;
- X default:
- X printf("uucico: warning, bad flag %s\n", argv[i]);
- X break;
- X }
- X }
- X
- X /* If argument provided, use it as name of comm port */
- X
- X /* FIXME, this needs some thought. */
- X
- X getcwd(path,128);
- X if (chdir(SPOOLDIR)) {
- X perror("Can't chdir to Spool directory");
- X exit(2);
- X }
- X
- X read_ctl(); /* Read control file FIXME */
- X
- X /*
- X * If running via getty/login, our debug stdout had better
- X * go to a file, not to the usual stdout!
- X */
- X
- X if (debug > 0 && Getty) {
- X freopen("T:uuslave.log", "a", stdout);
- X }
- X
- X setvbuf(stdout, NULL, _IOLBF, 0);
- X
- X /* Timestamp the long debug log */
- X
- X if (debug > 0) {
- X long clock;
- X
- X time(&clock);
- X printf("\014\nuuslave log on tty '%s' starting %s\n",
- X ttynam, ctime(&clock));
- X }
- X
- X /* Log our presence so we humans reading the logs can find the
- X entries created by uuslave. */
- X
- X ulog(-1, "Startup %s", VERSION);
- X
- X amiga_setup();
- X
- X modem_init();
- X
- X if (poll_sys) {
- X if (*poll_sys == '\0')
- X poll_sys = (char *)NULL;
- X call_system(poll_sys);
- X if (!f_wait)
- X goto end;
- X } else {
- X if (rmode) {
- X do_outbound();
- X if (!f_wait)
- X goto end;
- X }
- X }
- X
- X do {
- X /*
- X * Set up serial channel, wait for incoming call.
- X */
- X DEBUG(0, "\nRestarting\n", 0);
- X
- X if (Getty == 0 && Overide == 0)
- X openline();
- X
- X do_session(Getty);
- X
- X hangup();
- X DEBUG(0, "\nEnd of call\n", 0);
- X } while (loop && !Getty);
- X
- Xend:
- X cleanup();
- X}
- X
- X/*
- X * translate embedded escape characters
- X */
- X
- Xvoid
- Xxlat_str(msg, out)
- Xchar *msg;
- Xchar *out;
- X{
- X int i = 0;
- X int cr = 1;
- X /*int j = 0;*/
- X
- X while (msg[i]) {
- X if (msg[i] == '\\') {
- X switch (msg[++i]) {
- X case 'r': /* carriage return */
- X twrite("\r", 1);
- X /*out[j++] = 0x0d;*/
- X break;
- X case 'n': /* line feed */
- X twrite("\n", 1);
- X /*out[j++] = 0x0a;*/
- X break;
- X case '\\': /* back slash */
- X twrite("\\", 1);
- X /*out[j++] = '\\';*/
- X break;
- X case 't': /* tab */
- X twrite("\t", 1);
- X /*out[j++] = '\t';*/
- X break;
- X case 'b':
- X SendBreak();
- X break;
- X case 'd': /* delay */
- X Delay(180);
- X break;
- X case 's': /* space */
- X twrite(" ", 1);
- X /*out[j++] = ' ';*/
- X break;
- X case 'c': /* no CR at end */
- X cr = 0;
- X break;
- X default: /* don't know so skip it */
- X break;
- X }
- X ++i;
- X } else {
- X twrite(msg + i, 1);
- X ++i;
- X /*out[j++] = msg[i++];*/
- X }
- X }
- X if (cr) {
- X twrite("\r", 1);
- X /*out[j++] = 0x0d;*/
- X }
- X /*out[j] = '\0';*/
- X}
- X
- X/*
- X * Read the control file and grab a few parameters.
- X */
- X
- Xread_ctl()
- X{
- X FILE *fd;
- X static char buf[MAX_CTLLINE];
- X
- X if (!(fd = fopen("UULIB:Config", "r"))) {
- X printf("Can't Find config file");
- X chdir(path);
- X exit(3);
- X }
- X
- X /* find path to inbound news */
- X
- X while (NULL != fgets(buf, sizeof buf, fd)) {
- X if (strncmp(buf, "NodeName", 8) == 0) {
- X if (OurNameOv == 0)
- X strcpy(our_name, strtok(&buf[9], CTL_DELIM) ) ;
- X } else if (strncmp(buf, "Debug", 5) == 0)
- X if (debug < 0)
- X debug = atoi(strtok(&buf[6], CTL_DELIM));
- X }
- X fclose(fd);
- X return (1);
- X}
- X
- X/*
- X * Search spool queues for work, call the systems we need to call.
- X */
- X
- Xdo_outbound()
- X{
- X return call_system((char *)NULL);
- X}
- X
- X/*
- X * Call a specific system, or all systems that have work pending.
- X */
- X
- Xcall_system(sys)
- Xchar *sys;
- X{
- X FILE *lsys;
- X static char buf[MAX_LSYS];
- X static char sysnam[MAX_HOST];
- X static char prev_name[MAX_HOST];
- X int called = FAIL;
- X
- X /*
- X * Unix uucico just reads the directory, and calls the systems
- X * in the order of the files in the directory. We want more
- X * control than that, though I'm not sure that L.sys order is
- X * best either. For example, in the first call after 11PM,
- X * I'd like to call the sites that haven't been callable before
- X * 11PM first, and finish up with the ones I've been able to call
- X * all day. FIXME.
- X */
- X
- X if (! (lsys = fopen("UULIB:L.sys", "r"))) {
- X DEBUG(0, "uucico: can't open L.sys, errno %d\n", errno);
- X return 0;
- X }
- X sysnam[0] = '\0'; /* Initially, no previous sys */
- X
- X /* Once per system in L.sys... */
- X /* FIXME, handle continuation lines (trailing "\") */
- X
- X while (fgets(buf, sizeof buf, lsys)) {
- X if (buf[0] == '#' || buf[0] == '\n')
- X continue;
- X
- X /*
- X * Grab the system name. If same as previous, and
- X * the previous call worked, skip it.
- X */
- X
- X strcpy(prev_name, sysnam);
- X (void) sscanf(buf, "%s", sysnam);
- X if (!strcmp(sysnam, prev_name)) {
- X if (called == SUCCESS)
- X continue;
- X }
- X
- X /*
- X * If a system name was specified, skip til we find it
- X * If none was specified, only call if there is work.
- X */
- X
- X if (sys) {
- X if (strcmp(sys, sysnam) != 0)
- X continue;
- X } else {
- X DEBUG(3,"searching for outbound to %s\n", sysnam);
- X if (!work_scan(sysnam)) {
- X DEBUG(3,"no work for %s\n", sysnam);
- X called = SUCCESS; /* Don't try further */
- X continue;
- X }
- X DEBUG(2, "uucico: found work for %s\n", sysnam);
- X }
- X
- X called = call_sysline(buf);
- X
- X if (called == SUCCESS && sys)
- X break;
- X }
- X
- X fclose(lsys);
- X if (called == FAIL && sys)
- X DEBUG(0, "Could not call system %s\n", sys);
- X return 0;
- X}
- X
- X/*
- X * Call out to a system, given its L.sys line.
- X */
- X
- Xcall_sysline(lsysline)
- Xchar *lsysline;
- X{
- X static char tempname[MAX_HOST + 30 + SLOP];
- X static char strbuf[MAX_STRING+SLOP];
- X char *sysnam,
- X *times,
- X *acu,
- X *sbaud,
- X *telno,
- X *send,
- X *expct;
- X int baud;
- X
- X who[0] = '-'; who[1] = '\0'; /* No user now (for logit) */
- X
- X /* FIXME, use the values it is ignoring here */
- X
- X sysnam = strtok(lsysline, " ");
- X times = strtok(NULL, " "); /* Time */
- X acu = strtok(NULL, " "); /* ACU */
- X sbaud = strtok(NULL, " "); /* Baud */
- X telno = strtok(NULL," "); /* phone */
- X
- X strcpy(host_name, sysnam);
- X
- X if ((!ignore_time_restrictions) && (strcmp(times,"Any"))) {
- X /* FIXME, check the time parameter and return FAIL if
- X * it does not allow calls now. Meanwhile, bounce
- X * all calls unless -S is specified. */
- X ulog(-1, "Wrong Time To Call %s", sysnam);
- X return FAIL;
- X }
- X
- X baud = atoi(sbaud);
- X
- X /* FIX ME, acu not implemented ? */
- X DEBUG(4, "Opening outgoing line %s\n", acu);
- X if (openout(acu, baud) != SUCCESS)
- X return FAIL;
- X
- X if (Overide == 0) {
- X if (dial_nbr(telno)) {
- X ulog(-1, "FAILED call to %s", host_name);
- X return FAIL;
- X }
- X }
- X
- X /* FIXME, log tty, baud rate, ... */
- X ulog(-1, "DIALED %s", host_name);
- X
- X /*
- X * Process send-expect strings.
- X * FIXME, deal with "-", BREAK, etc.
- X */
- X
- X while (send = (char*)strtok((char *)NULL, " ")) {
- X if (send[0] != '"' || send[1] != '"' || send[2] != '\0') {
- X if (instr(send, strlen(send)))
- X goto bort1;
- X }
- X
- X if (expct = (char*)strtok((char *)NULL, " ")) {
- X /* FIXME secondary strings, e.g. ogin:-EOT-ogin: */
- X xlat_str(expct, strbuf);
- X
- X /*twrite(strbuf, strlen(strbuf));*/
- X }
- X }
- X
- X /*
- X * FIXME, there should be a way to detect login/passwd
- X * failure here and keep doing the script rather than
- X * continuing to expect Shere at another login: prompt.
- X */
- X
- X ulog(-1, "SUCCEEDED call to %s", host_name);
- X
- X
- X if (getname(1)) /* get name */
- X goto bort1;
- X /* send response */
- X sprintf(tempname, "\20S%s -Q0 -x%d\0", our_name, debug);
- X twrite(tempname, strlen(tempname)+1); /* Including null */
- X
- X /* wait for ok message, wait for protocol request
- X * send protocol 'g' response */
- X /* FIXME, we don't actually wait for the ROK message, since
- X * it is immediately followed by the Pprotos message. We
- X * currently just look for a Pg message. This needs work.
- X * FIXME, WE CAN'T TALK TO SITES THAT SUPPORT more than 'g'.
- X */
- X
- X if (instr(msgo3a, sizeof(msgo3a)-1)) {
- X if (!get_proto())
- X goto bort1;
- X }
- X
- X
- X twrite( msgi3, sizeof(msgi3)-1);
- X
- X if (turnon(1))
- X goto bort1;
- X
- X ulog(-1, "OK Startup");
- X
- X top_level(1);
- X hangup();
- X return SUCCESS;
- X
- Xbort1:
- X hangup();
- X return FAIL;
- X}
- X
- X/* Handle a single uucp [slave] login session */
- X
- Xdo_session(ontheline)
- Xint ontheline;
- X{
- X if (ontheline == 0) {
- X /* output login request, verify uucp */
- X twrite(msgo0,sizeof(msgo0)-1);
- X if (instr(msgi0,sizeof(msgi0)-1)) {
- X printf("uucico: invalid login name\n");
- X goto bort;
- X }
- X
- X /* output password request, verify s8000 */
- X twrite(msgo1,sizeof(msgo1)-1);
- X if (instr(msgi1,sizeof(msgi1)-1)) {
- X printf("uucico: invalid password\n");
- X goto bort;
- X }
- X
- X printf("uucico: correct login\n");
- X }
- X
- X /*
- X * send Shere=<myhost>
- X *
- X * Apparently mac UUCP has a bug that only allows 7
- X * char host names, and it fails if it gets shere=<myhost>
- X * where <myhost> is > 7 chars.
- X */
- X
- X /*strcpy(msgo2 + MSGO2IDX, our_name);*/
- X twrite(msgo2,strlen(msgo2)+1);
- X
- X /*
- X * get \020S<host> -Qn n (??)
- X */
- X
- X if (getname(0))
- X goto bort;
- X
- X /* output ok message, output protocol request, wait for response */
- X
- X twrite(msgo3,sizeof(msgo3)-1);
- X
- X /* FIXME, make the protocol list here, and use it */
- X twrite(msgo3b,sizeof(msgo3b)-1);
- X if (instr(msgi3,sizeof(msgi3)-1))
- X goto bort;
- X
- X if (turnon(0))
- X goto bort;
- X
- X ulog(-1, "OK Startup");
- X top_level(0);
- X
- Xbort:
- X if (debug > 0)
- X printf("uucico: call complete\n");
- X return (1);
- X}
- X
- X/*
- X * Handle transactions "at top level", as Unix uucp's debug log says.
- X *
- X * As master, we scan our queues for work and send requests to the
- X * other side. When done, we send a hangup request and switch to slave mode.
- X *
- X * As slave, we accept requests from the other side; when it is done,
- X * it sends a hangup request, and we switch to master mode, if we have
- X * any work queued up for that system.
- X *
- X * This repeats as long as either side has work to do. When all the
- X * queued work is done, we agree to hang up, terminate the packet protocol,
- X * and return to the caller. (We still haven't hung up the phone line yet.)
- X *
- X * A curious feature of the hangup protocol is that it is not a simple
- X * question-answer. The master says "H", asking about hangup. The
- X * slave responds "HY" saying OK. The master then says "HY" also,
- X * then both of them hang up. Maybe this is to make sure the first HY
- X * got ack'ed? Anyway, an "H" is reported as HANGUP and an "HY" as
- X * HANGNOW. After we send an HY, we go back to listening for commands;
- X * if the master sends something other than HY, we'll do it.
- X */
- X
- X#define HANGUP 2 /* Signal to switch master/slave roles */
- X#define HANGNOW 3 /* Signal to hang up now */
- X#define COPYFAIL 4 /* File copy failed */
- X
- Xint
- Xtop_level(master_mode)
- Xint master_mode;
- X{
- X static char buf[MAXMSGLEN]; /* For hangup responses */
- X
- X if (master_mode) {
- X (void) work_scan(host_name); /* Kick off queue scan */
- X goto master;
- X }
- X
- X for (;;) {
- X slave: /* SLAVE SIDE */
- X for (;;) {
- X DEBUG(4, "*** TOP *** - slave\n", 0);
- X switch (do_one_slave()) {
- X case SUCCESS:
- X break;
- X case FAIL:
- X return FAIL;
- X case HANGUP:
- X if (work_scan(host_name)) {
- X if (wrmsg("HN"))
- X return FAIL;
- X goto master;
- X } else {
- X if (wrmsg("HY"))
- X return FAIL;
- X break; /* go to master mode */
- X }
- X case HANGNOW:
- X goto quit;
- X }
- X }
- X master: /* MASTER SIDE */
- X for (;;) {
- X DEBUG(4, "*** TOP *** - master\n", 0);
- X switch (do_one_master()) {
- X case SUCCESS:
- X break;
- X case FAIL:
- X return FAIL;
- X case HANGUP:
- X /* We wrote an H command, what's the resp? */
- X if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
- X return FAIL;
- X }
- X if (buf[0] != 'H')
- X return FAIL;
- X if (buf[1] == 'N')
- X goto slave;
- X else {
- X /* Write the final HY */
- X if (wrmsg("HY"))
- X return FAIL;
- X goto quit;
- X }
- X }
- X }
- X }
- X
- Xquit:
- X /* Shut down the packet protocol */
- X
- X turnoff();
- X
- X /* Write the closing sequence */
- X
- X twrite(msgo4, sizeof(msgo4)-1);
- X (void) instr(msgi4, sizeof(msgi4)-1);
- X
- X twrite(msgo4, sizeof(msgo4)-1);
- X
- X strcpy(who, "-");
- X ulog(-1, "OK Conversation complete");
- X
- X return SUCCESS; /* Go byebye */
- X}
- X
- X/*
- X * We are slave; get a command from the other side and execute it.
- X *
- X * Result is SUCCESS, FAIL, HANGUP, or HANGNOW.
- X */
- X
- Xint
- Xdo_one_slave()
- X{
- X static char msg[MAXMSGLEN]; /* Master's message to us */
- X
- X /* Get master's command */
- X if (rdmsg(msg, MAXMSGLEN) != SUCCESS)
- X return FAIL;
- X
- X /* Print it for easy debugging */
- X DEBUG(5,"\nCommand: %s\n\n", msg);
- X
- X switch (msg[0]) {
- X case 'S':
- X if (msg[1] != ' ')
- X break;
- X return host_send_file(msg);
- X case 'R':
- X if (msg[1] != ' ')
- X break;
- X return host_receive_file(msg);
- X case 'X':
- X /*
- X * Cause uuxqt to run (on certain files?)
- X * See Protocol.doc for sketchy details.
- X */
- X break;
- X case 'H':
- X if (msg[1] == '\0') return HANGUP;
- X if (msg[1] == 'Y') return HANGNOW;
- X if (msg[1] == 'N') return SUCCESS; /* Ignore HN to slave */
- X break;
- X }
- X
- X /* Unrecognized packet from the other end */
- X
- X DEBUG(0, "Bad control packet refused: %s\n", msg);
- X if (yesno(msg[0], 0, 0)) /* FIXME: return error code */
- X return FAIL;
- X return SUCCESS;
- X}
- X
- X/*
- X * Do one piece of work as master.
- X *
- X * FIXME: we don't handle the flags, e.g. -c, properly!
- X *
- X * Now only dequeues queue file if all transfers were successful.
- X */
- X
- Xint
- Xdo_one_master()
- X{
- X FILE *fd;
- X char *sname;
- X char cmnd[1]; /* Command character */
- X static char buf[256];
- X int fail = SUCCESS;
- X int failaccum = 0;
- X int num;
- X int delmeflag;
- X static char notify[NAMESIZE]; /* A bit large...FIXME */
- X char *delList[16]; /* delete files list */
- X short di = 0;
- X
- X /* FIXME: do the notify stuff */
- X
- X sname = work_next();
- X if (!sname) {
- X /* No more work, time to hang up. */
- X if (wrmsg("H"))
- X return FAIL;
- X return HANGUP;
- X }
- X
- X DEBUG(2, "Request file %s\n", sname);
- X
- X LockFile(sname);
- X
- X fd = fopen(sname, "r");
- X if (fd == NULL) {
- X UnLockFile(sname);
- X DEBUG(0, "uucico: couldn't open %s\n", sname);
- X return SUCCESS;
- X }
- X
- X while (fgets(buf, sizeof buf, fd)) {
- X DEBUG(3, "Queued request: %s", buf);
- X
- X if (buf[1] != ' ')
- X goto badnum;
- X
- X num = sscanf(buf, "%s %s %s %s %s %s %o\n",
- X cmnd, srcnam, dstnam, who, flags, temp, &mode, notify
- X );
- X
- X switch (cmnd[0]) {
- X case 'S':
- X if (num < 7 || num > 8)
- X goto badnum;
- X fail = local_send_file(buf, &delmeflag);
- X if (delmeflag) {
- X if (di == sizeof(delList)/sizeof(delList[0])) {
- X ulog(-1, "Too many source files in Cmd file! %s", sname);
- X } else {
- X delList[di] = malloc(strlen(temp) + 1);
- X strcpy(delList[di], temp);
- X ++di;
- X }
- X }
- X break;
- X case 'R':
- X if (num != 5)
- X goto badnum;
- X fail = local_receive_file(buf);
- X break;
- X default:
- X badnum:
- X DEBUG(0, "Unknown/invalid queued request: %s\n", buf);
- X ++fail;
- X break;
- X }
- X if (fail != SUCCESS)
- X ++failaccum;
- X
- X /* FIXME, what does uucp do if one of N xfers fails? */
- X
- X if (fail == FAIL) {
- X ulog(-1, "Error in work file %s", sname);
- X ulog(-1, "Bad line is: %s", buf);
- X }
- X }
- X fclose(fd);
- X
- X /*
- X * If we successfuly copied everything zap the queue file
- X * and any local data files...
- X */
- X
- X if (failaccum == 0) {
- X while (di) {
- X --di;
- X remove(delList[di]);
- X free(delList[di]);
- X }
- X fail = remove(sname);
- X UnLockFile(sname);
- X if (fail != 0) {
- X ulog(-1, "Unable to remove work file %s", sname);
- X DEBUG(0, "Can't remove, errno %d\n", errno);
- X } else {
- X DEBUG(4, "Removed work file %s\n", sname);
- X }
- X } else {
- X UnLockFile(sname);
- X }
- X return SUCCESS;
- X}
- X
- X/* Send a "yes or no" packet with character 'c'. */
- X
- Xint
- Xyesno(c, true, err)
- Xchar c;
- Xint true;
- Xint err;
- X{
- X char buf[21];
- X
- X buf[0] = c;
- X buf[1] = true? 'Y': 'N';
- X buf[2] = 0;
- X if (err && !true)
- X sprintf(buf+2,"%d", err);
- X
- X return wrmsg(buf);
- X}
- X
- X/*
- X * SLAVE MODE, Master wishes to send a file to us
- X *
- X * SECURITY: If file is not in list of allowed directories
- X * disallow transfer. UUSPOOL: is always in the
- X * list.
- X *
- X * If file is for UUSPOOL: (the current dir), disallow "C." files
- X * NOTE: success return and file redirected to T: as this can
- X * occur only if somebody purposefully is trying to break us.
- X *
- X * Return 0 = success
- X */
- X
- Xint
- Xhost_send_file(msg)
- Xchar *msg;
- X{
- X FILE *fddsk; /* Disk file pointer */
- X char cmnd[1]; /* Command character */
- X int r;
- X int nor = 0;
- X
- X sscanf(msg,"%s %s %s %s %s %s %o",
- X cmnd, srcnam, dstnam, who, flags, temp, &mode);
- X
- X ulog(-1, "REQUESTED %s", msg);
- X munge_filename(dstnam, dstnam); /* Translate to local name */
- X strcpy (temp, TmpFileName(dstnam)); /* Create a handy temp file */
- X
- X if (SecurityDisallow(dstnam, 'w')) {
- X ulog(-1, "REQUEST FAILED -- SECURITY");
- X if (yesno('S', 0, 4))
- X return FAIL;
- X return SUCCESS;
- X }
- X if (SecurityDisallow(dstnam, 'c') > 0) {
- X ulog(-1, "REQUEST FAILED -- SECURITY, REMOTE TRIED TO SEND");
- X ulog(-1, "US A COMMAND FILE: %s, FILE COPIED TO T:Bad-Cmd", dstnam);
- X strcpy(dstnam, "T:Bad-Cmd");
- X nor = 1;
- X }
- X
- X /* FIXME: deal with file modes now that we fopen. */
- X
- X LockFile(temp);
- X
- X fddsk = fopen(temp, "wb" /*, mode|0600 */);
- X if (fddsk == NULL) {
- X UnLockFile(temp);
- X /* Can't open file -- send error response */
- X if (debug > 0) {
- X printf("Cannot open temp file %s (%s) for writing, errno=%d\n",
- X temp,
- X dstnam,
- X errno
- X );
- X }
- X ulog(-1, "REQUEST FAILED -- TEMP FILE");
- X if (yesno('S', 0, 4))
- X return FAIL;
- X return SUCCESS;
- X }
- X
- X /* FIXME: Are the above permissions right?? */
- X /* FIXME: Should we create directories for the file? */
- X
- X if (yesno('S',1, 0)) { /* Say yes */
- X fclose(fddsk);
- X unlink(temp);
- X UnLockFile(temp);
- X return 1;
- X }
- X r = receive_file(fddsk, temp, dstnam, srcnam, nor);
- X UnLockFile(temp);
- X return(r);
- X}
- X
- X/*
- X * SLAVE MODE, Master wants us to send a file to it
- X *
- X * SECURITY: If file is not in list of allowed directories
- X * disallow transfer. UUSPOOL: is always in the
- X * list.
- X *
- X * 0 = sucess
- X */
- X
- Xhost_receive_file(msg)
- Xchar *msg;
- X{
- X FILE *fddsk; /* Disk file descriptor */
- X int x;
- X char cmnd[1]; /* Command character */
- X
- X ulog(-1, "REQUESTED %s", msg);
- X
- X sscanf(msg,"%s %s %s",cmnd,srcnam,dstnam);
- X munge_filename(srcnam, temp);
- X
- X if (SecurityDisallow(srcnam, 'r')) {
- X ulog(-1, "COPY FAILED -- SECURITY");
- X if (yesno('S', 0, 4))
- X return FAIL;
- X return SUCCESS;
- X }
- X
- X fddsk = fopen(temp, "rb"); /* Try to open the file */
- X if (fddsk == NULL) {
- X /* File didn't open, sigh. */
- X if (debug > 0) {
- X printf("Cannot open file %s (%s) for reading, errno=%d\n",
- X temp, srcnam, errno
- X );
- X }
- X ulog(-1, "DENIED CAN'T OPEN %s", temp);
- X if (yesno('R', 0, 2))
- X return 1;
- X return 0;
- X }
- X
- X if (yesno('R',1, 0)) { /* Say yes */
- X fclose(fddsk);
- X return 1;
- X }
- X
- X x = send_file(fddsk);
- X
- X switch (x) {
- X default:
- X return x;
- X case COPYFAIL:
- X /* We don't care if the copy failed, since the master
- X asked for the file and knows the result. */
- X return SUCCESS;
- X }
- X return 1;
- X}
- X
- X/*
- X * MASTER MODE, We want to send a file.
- X *
- X * Return FAIL, SUCCESS, or COPYFAIL.
- X *
- X * SUCCESS is returned either if the file was not found locally (local
- X * error, and the queued transfer should be flushed) or if it was moved
- X * successfully. COPYFAIL indicates that the queued transfer should be
- X * left queued, and later retried. FIXME, there are several failure points
- X * in the transaction (see Protocol.doc) and we need finer control here.
- X */
- X
- Xint
- Xlocal_send_file(workstr, delmeflag)
- Xchar *workstr;
- Xint *delmeflag;
- X{
- X static char buf[MAXMSGLEN]; /* Used for both xmit and receive */
- X FILE *fddsk; /* Disk file descriptor */
- X int res; /* Result and file removal status */
- X
- X *delmeflag = 0;
- X
- X /* WHY are temp and srcnam switched? FIXME! And no notify? */
- X
- X sprintf(buf,"S %s %s %s %s %s 0%o %s",
- X temp, dstnam, who, flags, srcnam, mode, who
- X );
- X
- X ulog(-1, "REQUEST %s", buf);
- X
- X if (strchr(flags, 'c')) {
- X munge_filename(srcnam, temp);
- X } else {
- X munge_filename(temp, temp);
- X }
- X LockFile(temp);
- X fddsk = fopen(temp, "rb");
- X if (fddsk == NULL) {
- X UnLockFile(temp);
- X /* FIXME -- handle queued request for nonexistent file */
- X if (debug > 0)
- X printf("Can't open file %s (%s), errno=%d\n",
- X temp,
- X srcnam,
- X errno
- X );
- X ulog(-1, "NOT FOUND %s", temp);
- X /* return COPYFAIL;*/
- X return SUCCESS; /* assume file previously sent */
- X }
- X
- X /* Tell the other side we want to send this file */
- X
- X if (wrmsg(buf) != SUCCESS) {
- X DEBUG(0, "problem sending request\n", 0);
- X fclose(fddsk);
- X UnLockFile(temp);
- X return FAIL;
- X }
- X
- X /* See what they have to say about it */
- X
- X if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
- X fclose(fddsk);
- X UnLockFile(temp);
- X return FAIL;
- X }
- X if ((buf[0] != 'S') || (buf[1] != 'Y')) {
- X ulog(-1, "REQUEST DENIED %s", buf);
- X fclose(fddsk);
- X UnLockFile(temp);
- X return FAIL;
- X }
- X res = send_file(fddsk); /* FAIL, SUCCESS, or COPYFAIL */
- X
- X /* Delete the source file if it was just a copy */
- X
- X if (res != SUCCESS) {
- X UnLockFile(temp);
- X return res;
- X }
- X if (strchr(flags, 'c')) { /* If copied direct from source */
- X UnLockFile(temp);
- X return res; /* ...just return. */
- X }
- X *delmeflag = 1;
- X UnLockFile(temp);
- X
- X return res;
- X}
- X
- X/*
- X * MASTER MODE, We wish to receive a specific file so we ask for it
- X *
- X * Return 0 = success
- X */
- X
- Xint
- Xlocal_receive_file()
- X{
- X static char buf[MAXMSGLEN];
- X FILE *fddsk; /* Disk file pointer */
- X int r;
- X
- X /* FIXME, test dest file access before we ask for it. */
- X
- X sprintf(buf,"R %s %s %s %s %s 0%o %s",
- X srcnam, dstnam, who, flags, temp, mode, who
- X );
- X
- X munge_filename(dstnam, dstnam); /* tlate to local name */
- X strcpy (temp, TmpFileName(dstnam)); /* Create a handy temp file */
- X
- X /* FIXME: deal with file modes now that we fopen. */
- X /* FIXME: Are the above permissions right?? */
- X /* FIXME: Should we create directories for the file? */
- X
- X LockFile(temp);
- X fddsk = fopen(temp, "wb" /*, mode|060 */);
- X
- X if (fddsk == NULL) {
- X UnLockFile(temp);
- X /* Can't open temp file -- send error response */
- X if (debug > 0) {
- X printf("Cannot open temp file %s (%s) for writing, errno=%d\n",
- X temp,
- X dstnam,
- X errno
- X );
- X }
- X ulog(-1, "REQUEST FAILED -- TEMPFILE");
- X return FAIL;
- X }
- X
- X ulog(-1, "REQUEST %s", buf);
- X if (wrmsg(buf) != SUCCESS) {
- X fclose(fddsk);
- X UnLockFile(temp);
- X printf("uucico: problem sending request\n");
- X return FAIL;
- X }
- X
- X /* See what the other side has to say about it */
- X
- X if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
- X fclose(fddsk);
- X UnLockFile(temp);
- X return FAIL;
- X }
- X if ((buf[0] != 'R') || (buf[1] != 'Y')) {
- X ulog(-1, "REQUEST DENIED %s", buf);
- X fclose(fddsk);
- X UnLockFile(temp);
- X return SUCCESS; /* FIXME, should do something more here */
- X }
- X
- X r = receive_file(fddsk, temp, dstnam, srcnam, 0);
- X UnLockFile(temp);
- X return(r);
- X}
- X
- X/*
- X * General receive file
- X */
- X
- Xint
- Xreceive_file(fddsk, temp, dstnam, srcnam, norename)
- XFILE *fddsk;
- Xchar *temp, *dstnam, *srcnam;
- X{
- X int status;
- X int error = 0; /* No errors so far */
- X
- X if (rddata(fddsk) != SUCCESS)
- X error++;
- X status = fclose(fddsk); /* Make sure the data got here */
- X if (status != 0) {
- X error++;
- X DEBUG(0, "fclose errno=%d\n", errno);
- X }
- X
- X /*
- X * Move the file from its temp location to its real location,
- X * This needs to be able to copy a file if a simple rename
- X * does not suffice. Should create directories if necesary.
- X * should use source ]name if target is a directory (i.e. no
- X * target source name
- X */
- X
- X unlink(dstnam);
- X
- X if (norename) /* for security redirect */
- X status = 0;
- X else
- X status = rename(temp, dstnam);
- X
- X if (status != 0) {
- X error++;
- X if (debug > 0) {
- X printf("Cannot rename file %s to %s, errno=%d\n",
- X temp, dstnam, errno);
- X }
- X }
- X
- X ulog(-1, "COPY %s", error ? "FAILED": "SUCCEEDED");
- X
- X if (yesno('C', error == 0, 5)) /* Send yes or no */
- X return FAIL;
- X
- X return SUCCESS;
- X}
- X
- X/*
- X * general file send routine
- X * Return SUCCESS, FAIL, or COPYFAIL.
- X */
- X
- Xint
- Xsend_file(fddsk)
- XFILE *fddsk; /* Disk file pointer */
- X{
- X static char ansbuf[MAXMSGLEN];
- X
- X if (wrdata(fddsk) != SUCCESS) {
- X fclose(fddsk);
- X return COPYFAIL;
- X }
- X fclose(fddsk);
- X
- X /* Await the "CY" or "CNddd" packet, and toss it. */
- X
- X while (1) {
- X if (rdmsg(ansbuf, MAXMSGLEN) != SUCCESS)
- X return COPYFAIL;
- X if (ansbuf[0] != 'C') {
- X DEBUG(0,"\nDidn't get 'CY' or 'CN', got %s\n", ansbuf);
- X /* and loop looking for C message */
- X } else if (ansbuf[1] == 'Y') {
- X ulog(-1, "REQUESTED %s", ansbuf);
- X return SUCCESS;
- X } else {
- X ulog(-1, "COPY FAILED %s", ansbuf);
- X return COPYFAIL;
- X }
- X }
- X return COPYFAIL;
- X}
- X
- END_OF_FILE
- if test 32949 -ne `wc -c <'src/uucico/uucico.c'`; then
- echo shar: \"'src/uucico/uucico.c'\" unpacked with wrong size!
- fi
- # end of 'src/uucico/uucico.c'
- fi
- echo shar: End of archive 11 \(of 16\).
- cp /dev/null ark11isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 16 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
- amiga@cs.odu.edu
- or amiga@xanth.cs.odu.edu ( obsolescent mailers may need this address )
- or ...!uunet!xanth!amiga ( very obsolescent mailers need this address )
-
- Comments, questions, and suggestions should be addressed to ``amiga-request''
- (please only use ``amiga'' for actual submissions) at the above addresses.
-